package repository

import (
	"context"
	"database/sql"
	"encoding/json"
	"fmt"
	"strings"
	"time"

	"mall/common/globalkey"
	"mall/common/modelx"
	"mall/service/order/model"

	"github.com/sirupsen/logrus"
	"github.com/volatiletech/null/v8"
	"github.com/volatiletech/sqlboiler/v4/boil"
	"github.com/volatiletech/sqlboiler/v4/queries/qm"
	"github.com/zeromicro/go-zero/core/stores/cache"
)

type (
	// OrderRepository is an interface to be customized, add more methods here,
	// and implement the added methods in customOrderRepository.
	OrderRepository interface {
		FindOne(ctx context.Context, id uint64) (*model.Order, error)
		FindOneWithExpire(
			ctx context.Context,
			id uint64,
			expire time.Duration,
		) (*model.Order, error)
		FindOneNoCache(
			ctx context.Context,
			conn boil.ContextExecutor,
			id uint64,
		) (*model.Order, error)
		GetList(
			ctx context.Context,
			cols model.M,
			withCount int,
			filter map[string]map[string][]any,
		) ([]*model.Order, int64, error) // ##25.04.29#
		Insert(
			ctx context.Context,
			tx boil.ContextExecutor,
			data *model.Order,
			rel *model.OrderRel,
		) error
		Update(
			ctx context.Context,
			tx boil.ContextExecutor,
			data *model.Order,
			rel *model.OrderRel,
		) error
		UpdateBatch(ctx context.Context, tx boil.ContextExecutor, ids []uint64, cols model.M) error
		SoftDelete(ctx context.Context, tx boil.ContextExecutor, id uint64) error
		Restore(ctx context.Context, tx boil.ContextExecutor, id uint64) error
		GetAddressList(
			ctx context.Context,
			cols model.M,
			withCount int,
			filter map[string]map[string][]any,
		) ([]*model.OrderAddress, int64, error) // ##25.04.29#
		GetAdjustmentList(
			ctx context.Context,
			cols model.M,
			withCount int,
			filter map[string]map[string][]any,
		) ([]*model.OrderAdjustment, int64, error) // ##25.04.29#
		GetDiscountList(
			ctx context.Context,
			cols model.M,
			withCount int,
			filter map[string]map[string][]any,
		) ([]*model.OrderDiscount, int64, error) // ##25.04.30#
		GetItemList(
			ctx context.Context,
			cols model.M,
			withCount int,
			filter map[string]map[string][]any,
		) ([]*model.OrderItem, int64, error) // ##25.04.29#
		GetLogList(
			ctx context.Context,
			cols model.M,
			withCount int,
			filter map[string]map[string][]any,
		) ([]*model.OrderOperateLog, int64, error) // ##25.04.30#
		GetPaymentList(
			ctx context.Context,
			cols model.M,
			withCount int,
			filter map[string]map[string][]any,
		) ([]*model.OrderPayment, int64, error) // ##25.04.30#
		GetShipmentList(
			ctx context.Context,
			cols model.M,
			withCount int,
			filter map[string]map[string][]any,
		) ([]*model.OrderShipment, int64, error) // ##25.04.30#
		GetRefundList(
			ctx context.Context,
			cols model.M,
			withCount int,
			filter map[string]map[string][]any,
		) ([]*model.OrderRefund, int64, error)
		UpdateShipment(
			ctx context.Context,
			tx boil.ContextExecutor,
			data *model.OrderShipment,
		) error // ##25.06.12##
		InsertShipment(
			ctx context.Context,
			tx boil.ContextExecutor,
			data *model.OrderShipment,
		) error // ##25.06.12##
	}

	customOrderRepository struct {
		modelx.CachedConn
		mysqlConn           *sql.DB
		cacheIdPrefix       string
		cacheIdExpirePrefix string
	}
)

// NewOrderRepository returns a repository for the database table.
func NewOrderRepository(mysqlConn *sql.DB, cacheConf cache.CacheConf) OrderRepository {
	return &customOrderRepository{
		CachedConn:          modelx.NewConn(mysqlConn, cacheConf),
		mysqlConn:           mysqlConn,
		cacheIdPrefix:       "cache:order:orders:id:",
		cacheIdExpirePrefix: "cache:order:orders:id:expire:",
	}
}

func (r *customOrderRepository) FindOne(
	ctx context.Context,
	id uint64,
) (*model.Order, error) {
	cacheIdKey := r.formatPrimary(id)
	var resp model.Order
	err := r.QueryCtx(ctx, &resp, cacheIdKey, func(ctx context.Context, conn *sql.DB, v any) error {
		data, err := model.FindOrder(ctx, conn, id)
		if err != nil {
			return err
		}

		*v.(*model.Order) = *data

		return nil
	})

	switch err {
	case nil:
		return &resp, nil
	case sql.ErrNoRows:
		return nil, model.ErrNotFound
	default:
		return nil, err
	}
}

func (r *customOrderRepository) FindOneWithExpire(
	ctx context.Context,
	id uint64,
	expire time.Duration,
) (*model.Order, error) {
	cacheIdKey := r.formatPrimary(id)
	var resp model.Order
	err := r.QueryWithExpireCtx(ctx, &resp, cacheIdKey, expire, func(ctx context.Context, conn *sql.DB, v any) error {
		data, err := model.FindOrder(ctx, conn, id)
		if err != nil {
			return err
		}

		*v.(*model.Order) = *data

		return nil
	})

	switch err {
	case nil:
		return &resp, nil
	case sql.ErrNoRows:
		return nil, model.ErrNotFound
	default:
		return nil, err
	}
}

func (r *customOrderRepository) FindOneNoCache(
	ctx context.Context,
	conn boil.ContextExecutor,
	id uint64,
) (*model.Order, error) {
	var db boil.ContextExecutor = r.mysqlConn
	if conn != nil {
		db = conn
	}
	data, err := model.FindOrder(ctx, db, id)
	logrus.Info(fmt.Sprintf("FindOneNoCache err: %+v", err))
	switch err {
	case nil:
		return data, nil
	case sql.ErrNoRows:
		return nil, model.ErrNotFound
	default:
		return nil, err
	}
}

func (r *customOrderRepository) GetList(
	ctx context.Context,
	cols model.M,
	withCount int,
	filter map[string]map[string][]any,
) (list []*model.Order, count int64, err error) {
	var page int
	var pageSize int
	var limit int
	var selectCol string
	var mods []qm.QueryMod
	var nextCount int64
	var previousCount int64
	var statistic bool
	for k, v := range cols {
		switch k {
		case "page":
			if val, ok := v.(uint64); ok && val > 1 {
				page = int(val)
			}
		case "pageSize":
			if val, ok := v.(uint64); ok && val > 0 {
				pageSize = int(val)
			}
		case "limit":
			if val, ok := v.(uint32); ok && val > 0 {
				limit = int(val)
			}
		case "offset":
			if withCount == 2 {
				if val, ok := v.(uint32); ok && val > 0 {
					mods = append(mods, qm.Offset(int(val)))
					previousCount = 1
				}
			}
		case "orderBy":
			if val, ok := v.(string); ok && len(val) > 0 {
				mods = append(mods, qm.OrderBy(val))
			}
		case "preMinId":
			if withCount == 3 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.OrderColumns.ID+" DESC"))
					mods = append(mods, model.OrderWhere.ID.LT(val))
					previousCount = 1
				}
			}
		case "preMaxId":
			if withCount == 4 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.OrderColumns.ID+" ASC"))
					mods = append(mods, model.OrderWhere.ID.GT(val))
					previousCount = 1
				}
			}
		case "select":
			if withCount != 5 {
				if val, ok := v.(string); ok && len(val) > 0 {
					selectCol = val
				}
			}
		case "statistic":
			if val, ok := v.(string); ok && val == "1" { // 按 Status 统计
				statistic = true
			}
		}
	}

	for key, opMap := range filter {
		switch key {
		case model.OrderColumns.ID:
			mods = append(mods, modelx.GetIntMods(model.OrderColumns.ID, opMap)...)
		case model.OrderColumns.ParentID:
			mods = append(mods, modelx.GetIntMods(model.OrderColumns.ParentID, opMap)...)
		case model.OrderColumns.UserID:
			mods = append(mods, modelx.GetIntMods(model.OrderColumns.UserID, opMap)...)
		case model.OrderColumns.UserRank:
			mods = append(mods, modelx.GetStringMods(model.OrderColumns.UserRank, opMap)...)
		case model.OrderColumns.Buyer:
			mods = append(mods, modelx.GetStringMods(model.OrderColumns.Buyer, opMap)...)
		case model.OrderColumns.OrderSN:
			mods = append(mods, modelx.GetStringMods(model.OrderColumns.OrderSN, opMap)...)
		case model.OrderColumns.OrderType:
			mods = append(mods, modelx.GetIntMods(model.OrderColumns.OrderType, opMap)...)
		case model.OrderColumns.SourceType:
			mods = append(mods, modelx.GetIntMods(model.OrderColumns.SourceType, opMap)...)
		case model.OrderColumns.Quantity:
			mods = append(mods, modelx.GetIntMods(model.OrderColumns.Quantity, opMap)...)
		case model.OrderColumns.GemAmount:
			mods = append(mods, modelx.GetIntMods(model.OrderColumns.GemAmount, opMap)...)
		case model.OrderColumns.RetailAmount:
			mods = append(mods, modelx.GetIntMods(model.OrderColumns.RetailAmount, opMap)...)
		case model.OrderColumns.Freight:
			mods = append(mods, modelx.GetIntMods(model.OrderColumns.Freight, opMap)...)
		case model.OrderColumns.DiscountAmount:
			mods = append(mods, modelx.GetIntMods(model.OrderColumns.DiscountAmount, opMap)...)
		case model.OrderColumns.AdjustAmount:
			mods = append(mods, modelx.GetIntMods(model.OrderColumns.AdjustAmount, opMap)...)
		case model.OrderColumns.ActualAmount:
			mods = append(mods, modelx.GetIntMods(model.OrderColumns.ActualAmount, opMap)...)
		case model.OrderColumns.DepositAmount:
			mods = append(mods, modelx.GetIntMods(model.OrderColumns.DepositAmount, opMap)...)
		case model.OrderColumns.BalanceAmount:
			mods = append(mods, modelx.GetIntMods(model.OrderColumns.BalanceAmount, opMap)...)
		case model.OrderColumns.RemainingAmount:
			mods = append(mods, modelx.GetIntMods(model.OrderColumns.RemainingAmount, opMap)...)
		case model.OrderColumns.RefundAmount:
			mods = append(mods, modelx.GetIntMods(model.OrderColumns.RefundAmount, opMap)...)
		case model.OrderColumns.Gems:
			mods = append(mods, modelx.GetIntMods(model.OrderColumns.Gems, opMap)...)
		case model.OrderColumns.TradeState:
			mods = append(mods, modelx.GetIntMods(model.OrderColumns.TradeState, opMap)...)
		case model.OrderColumns.Remark:
			mods = append(mods, modelx.GetStringMods(model.OrderColumns.Remark, opMap)...)
		case model.OrderColumns.Synced:
			mods = append(mods, modelx.GetBooleanMods(model.OrderColumns.Synced, opMap)...)
		case model.OrderColumns.AutoComfirmDays:
			mods = append(mods, modelx.GetIntMods(model.OrderColumns.AutoComfirmDays, opMap)...)
		case model.OrderColumns.Growth:
			mods = append(mods, modelx.GetIntMods(model.OrderColumns.Growth, opMap)...)
		case model.OrderColumns.CreatedAt:
			mods = append(mods, modelx.GetTimeMods(model.OrderColumns.CreatedAt, opMap)...)
		case model.OrderColumns.UpdatedAt:
			mods = append(mods, modelx.GetTimeMods(model.OrderColumns.UpdatedAt, opMap)...)
		case model.OrderColumns.PaidAt:
			mods = append(mods, modelx.GetTimeMods(model.OrderColumns.PaidAt, opMap)...)
		case model.OrderColumns.ShippedAt:
			mods = append(mods, modelx.GetTimeMods(model.OrderColumns.ShippedAt, opMap)...)
		case model.OrderColumns.DeliveredAt:
			mods = append(mods, modelx.GetTimeMods(model.OrderColumns.DeliveredAt, opMap)...)
		case model.OrderColumns.ConfirmedAt:
			mods = append(mods, modelx.GetTimeMods(model.OrderColumns.ConfirmedAt, opMap)...)
		case model.OrderColumns.ReviewedAt:
			mods = append(mods, modelx.GetTimeMods(model.OrderColumns.ReviewedAt, opMap)...)
		case model.OrderColumns.FulfilledAt:
			mods = append(mods, modelx.GetTimeMods(model.OrderColumns.FulfilledAt, opMap)...)
		case model.OrderColumns.ClosedAt:
			mods = append(mods, modelx.GetTimeMods(model.OrderColumns.ClosedAt, opMap)...)
		}
	}

	if statistic {
		mods = append(mods, qm.Select(fmt.Sprintf(
			"%s, count(%s) as %s",
			model.OrderColumns.TradeState,
			model.OrderColumns.TradeState,
			model.OrderColumns.Growth,
		)))
		mods = append(mods, qm.GroupBy(model.OrderColumns.TradeState))
		preList, preErr := model.Orders(mods...).All(ctx, r.mysqlConn)
		if preErr != nil {
			err = preErr
			return
		}

		return preList, 0, nil
	}

	if withCount >= 2 {
		if limit > 0 {
			mods = append(mods, qm.Limit(limit+1))
		}
	} else if withCount >= 0 {
		count, err = model.Orders(mods...).Count(ctx, r.mysqlConn)
		if err != nil {
			return
		}

		if withCount == 0 {
			return
		}
	}

	if pageSize > 0 && (withCount == -1 || withCount == 1) {
		if page > 1 {
			mods = append(mods, qm.Offset(pageSize*(page-1)))
		}
		mods = append(mods, qm.Limit(pageSize))
	}

	var columns []string
	if len(selectCol) > 0 {
		if selectCol == "," {
			columns = append(columns, model.OrderColumns.ID)
		} else {
			columns = strings.Split(selectCol, ",")
		}
	}
	if len(columns) > 0 {
		mods = append(mods, qm.Select(columns...))
	}

	list, err = model.Orders(mods...).All(ctx, r.mysqlConn)
	if err != nil {
		return
	}

	if withCount >= 2 {
		if limit > 0 && len(list) > limit {
			nextCount = 1
			list = list[:limit]
		}
		count = previousCount + nextCount*2
	}

	return
}

func (r *customOrderRepository) Insert(
	ctx context.Context,
	tx boil.ContextExecutor,
	data *model.Order,
	rel *model.OrderRel,
) error {
	err := r.ExecCtx(ctx, func(ctx context.Context, conn *sql.DB) error {
		var db boil.ContextExecutor
		if tx != nil {
			db = tx
		} else {
			db = conn
		}

		err := data.Insert(ctx, db, boil.Infer())
		if err != nil {
			return err
		}

		if rel == nil {
			return nil
		}

		orderId := data.ID
		if len(rel.Adjustments) > 0 {
			for _, orderAdjustment := range rel.Adjustments {
				orderAdjustment.OrderID = orderId
				err = orderAdjustment.Insert(ctx, db, boil.Infer())
				if err != nil {
					return err
				}
			}
		}

		if len(rel.Addresses) > 0 {
			for _, orderAddress := range rel.Addresses {
				orderAddress.OrderID = orderId
				err = orderAddress.Insert(ctx, db, boil.Infer())
				if err != nil {
					return err
				}
			}
		}

		if len(rel.Discounts) > 0 {
			for _, orderDiscount := range rel.Discounts {
				orderDiscount.OrderID = orderId
				err = orderDiscount.Insert(ctx, db, boil.Infer())
				if err != nil {
					return err
				}
			}
		}

		if len(rel.Items) > 0 {
			for _, orderItem := range rel.Items {
				orderItem.OrderID = orderId
				err = orderItem.Insert(ctx, db, boil.Infer())
				if err != nil {
					return err
				}
			}
		}

		if len(rel.Payments) > 0 {
			for _, orderPayment := range rel.Payments {
				orderPayment.OrderID = orderId
				err = orderPayment.Insert(ctx, db, boil.Infer())
				if err != nil {
					return err
				}
			}
		}

		if len(rel.Shipments) > 0 {
			for _, orderShipment := range rel.Shipments {
				orderShipment.OrderID = orderId
				err = orderShipment.Insert(ctx, db, boil.Infer())
				if err != nil {
					return err
				}
			}
		}

		return nil
	}, r.getCacheKeys(data)...)

	return err
}

func (r *customOrderRepository) Update(
	ctx context.Context,
	tx boil.ContextExecutor,
	data *model.Order,
	rel *model.OrderRel,
) error {
	err := r.ExecCtx(ctx, func(ctx context.Context, conn *sql.DB) error {
		var db boil.ContextExecutor
		if tx != nil {
			db = tx
		} else {
			db = conn
		}

		rowsAff, err := data.Update(ctx, db, boil.Blacklist(
			model.OrderColumns.ID,
			model.OrderColumns.UserID,
			model.OrderColumns.OrderSN,
			model.OrderColumns.OrderType,
			model.OrderColumns.SourceType,
			model.OrderColumns.CreatedAt,
			model.OrderColumns.DeletedAt,
		))
		if err != nil {
			return err
		}

		if rowsAff == 0 {
			return model.ErrNotUpdated
		}

		if rel == nil {
			return nil
		}

		orderId := data.ID
		if len(rel.Items) > 0 {
			for _, orderItem := range rel.Items {
				if orderItem.OrderItemID > 0 {
					rowsAff, err = orderItem.Update(ctx, db, boil.Blacklist(
						model.OrderItemColumns.OrderItemID,
						model.OrderItemColumns.OrderID,
						model.OrderItemColumns.SkuID,
					))
					if err != nil {
						return err
					}
				} else {
					orderItem.OrderID = orderId
					err = orderItem.Insert(ctx, db, boil.Infer())
					if err != nil {
						return err
					}
				}
			}
		}

		if len(rel.Payments) > 0 {
			for _, orderPayment := range rel.Payments {
				if orderPayment.OrderPaymentID > 0 {
					rowsAff, err = orderPayment.Update(ctx, db, boil.Blacklist(
						model.OrderPaymentColumns.OrderPaymentID,
						model.OrderPaymentColumns.OrderID,
					))
					if err != nil {
						return err
					}
				} else {
					orderPayment.OrderID = orderId
					err = orderPayment.Insert(ctx, db, boil.Infer())
					if err != nil {
						return err
					}
				}
			}
		}

		if len(rel.Refunds) > 0 {
			for _, orderRefund := range rel.Refunds {
				if orderRefund.OrderRefundID > 0 {
					_, err = orderRefund.Update(ctx, db, boil.Blacklist(
						model.OrderRefundColumns.OrderRefundID,
						model.OrderRefundColumns.OrderID,
						model.OrderRefundColumns.OrderPaymentID,
					))
					if err != nil {
						return err
					}
				} else {
					orderRefund.OrderID = orderId
					err = orderRefund.Insert(ctx, db, boil.Infer())
					if err != nil {
						return err
					}
				}
			}
		}

		if len(rel.Logs) > 0 {
			for _, log := range rel.Logs {
				log.OrderID = orderId
				err = log.Insert(ctx, db, boil.Infer())
				if err != nil {
					return err
				}
			}
		}

		return nil
	}, r.getCacheKeys(data)...)

	return err
}

func (r *customOrderRepository) UpdateBatch(
	ctx context.Context,
	tx boil.ContextExecutor,
	ids []uint64,
	cols model.M,
) error {
	if len(ids) > 0 {
		err := r.ExecCtx(ctx, func(ctx context.Context, conn *sql.DB) error {
			var db boil.ContextExecutor
			if tx != nil {
				db = tx
			} else {
				db = conn
			}

			var mods []qm.QueryMod
			mods = append(mods, model.OrderWhere.ID.IN(ids))

			rowsAff, err := model.Orders(mods...).UpdateAll(ctx, db, cols)
			if err != nil {
				return err
			}

			if rowsAff == 0 {
				return model.ErrNotUpdated
			}

			return nil
		}, r.formatPrimaries(ids)...)

		return err
	}

	return nil
}

func (r *customOrderRepository) SoftDelete(
	ctx context.Context,
	tx boil.ContextExecutor,
	id uint64,
) error {
	data, err := r.FindOneNoCache(ctx, tx, id)
	if err != nil {
		if err == model.ErrNotFound {
			return nil
		}

		return err
	}

	if data.TradeState == uint16(globalkey.StatusDeleted) {
		return nil
	}

	data.DelState = data.TradeState
	data.TradeState = uint16(globalkey.StatusDeleted)
	data.DeletedAt = null.TimeFrom(time.Now())

	err = r.ExecCtx(ctx, func(ctx context.Context, conn *sql.DB) error {
		var db boil.ContextExecutor
		if tx != nil {
			db = tx
		} else {
			db = conn
		}

		rowsAff, err := data.Update(ctx, db, boil.Blacklist(
			model.OrderColumns.ID,
			model.OrderColumns.UpdatedAt,
		))
		if err != nil {
			return err
		}

		if rowsAff == 0 {
			return model.ErrNotUpdated
		}

		return nil
	}, r.getCacheKeys(data)...)

	return err
}

func (r *customOrderRepository) Restore(
	ctx context.Context,
	tx boil.ContextExecutor,
	id uint64,
) error {
	data, err := r.FindOneNoCache(ctx, tx, id)
	if err != nil {
		if err == model.ErrNotFound {
			return nil
		}

		return err
	}

	if data.TradeState != uint16(globalkey.StatusDeleted) {
		return nil
	}

	data.TradeState = data.DelState
	data.DeletedAt = null.TimeFromPtr(nil)

	err = r.ExecCtx(ctx, func(ctx context.Context, conn *sql.DB) error {
		var db boil.ContextExecutor
		if tx != nil {
			db = tx
		} else {
			db = conn
		}

		rowsAff, err := data.Update(ctx, db, boil.Blacklist(
			model.OrderColumns.ID,
			model.OrderColumns.UpdatedAt,
		))
		if err != nil {
			return err
		}

		if rowsAff == 0 {
			return model.ErrNotUpdated
		}

		return nil
	}, r.getCacheKeys(data)...)

	return err
}

func (r *customOrderRepository) getCacheKeys(data *model.Order) []string {
	if data == nil {
		return []string{}
	}

	cacheIdKey := r.formatPrimary(data.ID)
	cacheKeys := []string{
		cacheIdKey,
	}

	return cacheKeys
}

func (r *customOrderRepository) formatPrimary(primary any) string {
	return fmt.Sprintf("%s%v", r.cacheIdPrefix, primary)
}

func (r *customOrderRepository) formatPrimaries(primaries []uint64) []string {
	var resp []string
	for _, primary := range primaries {
		resp = append(resp, r.formatPrimary(primary))
	}

	return resp
}

func (r *customOrderRepository) queryPrimary(ctx context.Context, conn *sql.DB, v, primary any) error {
	var uid uint64
	if jsonId, ok := primary.(json.Number); ok {
		if int64Id, err := jsonId.Int64(); err == nil {
			uid = uint64(int64Id)
		} else {
			return err
		}
	}

	data, err := model.FindOrder(ctx, conn, uid)
	if err != nil {
		return err
	}

	*v.(*model.Order) = *data

	return nil
}

func (r *customOrderRepository) GetAddressList(
	ctx context.Context,
	cols model.M,
	withCount int,
	filter map[string]map[string][]any,
) (list []*model.OrderAddress, count int64, err error) {
	var page int
	var pageSize int
	var limit int
	var selectCol string
	var mods []qm.QueryMod
	var nextCount int64
	var previousCount int64
	for k, v := range cols {
		switch k {
		case "page":
			if val, ok := v.(uint64); ok && val > 1 {
				page = int(val)
			}
		case "pageSize":
			if val, ok := v.(uint64); ok && val > 0 {
				pageSize = int(val)
			}
		case "limit":
			if val, ok := v.(uint32); ok && val > 0 {
				limit = int(val)
			}
		case "offset":
			if withCount == 2 {
				if val, ok := v.(uint32); ok && val > 0 {
					mods = append(mods, qm.Offset(int(val)))
					previousCount = 1
				}
			}
		case "orderBy":
			if val, ok := v.(string); ok && len(val) > 0 {
				mods = append(mods, qm.OrderBy(val))
			}
		case "preMinId":
			if withCount == 3 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.OrderAddressColumns.OrderAddressID+" DESC"))
					mods = append(mods, model.OrderAddressWhere.OrderAddressID.LT(val))
					previousCount = 1
				}
			}
		case "preMaxId":
			if withCount == 4 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.OrderAddressColumns.OrderAddressID+" ASC"))
					mods = append(mods, model.OrderAddressWhere.OrderAddressID.GT(val))
					previousCount = 1
				}
			}
		case "select":
			if withCount != 5 {
				if val, ok := v.(string); ok && len(val) > 0 {
					selectCol = val
				}
			}
		}
	}

	for key, opMap := range filter {
		switch key {
		case model.OrderAddressColumns.OrderAddressID:
			mods = append(mods, modelx.GetIntMods(model.OrderAddressColumns.OrderAddressID, opMap)...)
		case model.OrderAddressColumns.OrderID:
			mods = append(mods, modelx.GetIntMods(model.OrderAddressColumns.OrderID, opMap)...)
		case model.OrderAddressColumns.UserID:
			mods = append(mods, modelx.GetIntMods(model.OrderAddressColumns.UserID, opMap)...)
		case model.OrderAddressColumns.Consignee:
			mods = append(mods, modelx.GetStringMods(model.OrderAddressColumns.Consignee, opMap)...)
		case model.OrderAddressColumns.Mobile:
			mods = append(mods, modelx.GetStringMods(model.OrderAddressColumns.Mobile, opMap)...)
		case model.OrderAddressColumns.Province:
			mods = append(mods, modelx.GetStringMods(model.OrderAddressColumns.Province, opMap)...)
		case model.OrderAddressColumns.City:
			mods = append(mods, modelx.GetStringMods(model.OrderAddressColumns.City, opMap)...)
		case model.OrderAddressColumns.District:
			mods = append(mods, modelx.GetStringMods(model.OrderAddressColumns.District, opMap)...)
		case model.OrderAddressColumns.Street:
			mods = append(mods, modelx.GetStringMods(model.OrderAddressColumns.Street, opMap)...)
		case model.OrderAddressColumns.DetailedAddress:
			mods = append(mods, modelx.GetStringMods(model.OrderAddressColumns.DetailedAddress, opMap)...)
		case model.OrderAddressColumns.PostalCode:
			mods = append(mods, modelx.GetStringMods(model.OrderAddressColumns.PostalCode, opMap)...)
		case model.OrderAddressColumns.RegionCode:
			mods = append(mods, modelx.GetStringMods(model.OrderAddressColumns.RegionCode, opMap)...)
		case model.OrderAddressColumns.Label:
			mods = append(mods, modelx.GetStringMods(model.OrderAddressColumns.Label, opMap)...)
		case model.OrderAddressColumns.Status:
			mods = append(mods, modelx.GetIntMods(model.OrderAddressColumns.Status, opMap)...)
		}
	}

	if withCount >= 2 {
		if limit > 0 {
			mods = append(mods, qm.Limit(limit+1))
		}
	} else if withCount >= 0 {
		count, err = model.OrderAddresses(mods...).Count(ctx, r.mysqlConn)
		if err != nil {
			return
		}

		if withCount == 0 {
			return
		}
	}

	if pageSize > 0 && (withCount == -1 || withCount == 1) {
		if page > 1 {
			mods = append(mods, qm.Offset(pageSize*(page-1)))
		}
		mods = append(mods, qm.Limit(pageSize))
	}

	var columns []string
	if len(selectCol) > 0 {
		if selectCol == "," {
			columns = append(columns, model.OrderAddressColumns.OrderAddressID)
		} else {
			columns = strings.Split(selectCol, ",")
		}
	}
	if len(columns) > 0 {
		mods = append(mods, qm.Select(columns...))
	}

	list, err = model.OrderAddresses(mods...).All(ctx, r.mysqlConn)
	if err != nil {
		return
	}

	if withCount >= 2 {
		if limit > 0 && len(list) > limit {
			nextCount = 1
			list = list[:limit]
		}
		count = previousCount + nextCount*2
	}

	return
}

func (r *customOrderRepository) GetAdjustmentList(
	ctx context.Context,
	cols model.M,
	withCount int,
	filter map[string]map[string][]any,
) (list []*model.OrderAdjustment, count int64, err error) {
	var page int
	var pageSize int
	var limit int
	var selectCol string
	var mods []qm.QueryMod
	var nextCount int64
	var previousCount int64
	for k, v := range cols {
		switch k {
		case "page":
			if val, ok := v.(uint64); ok && val > 1 {
				page = int(val)
			}
		case "pageSize":
			if val, ok := v.(uint64); ok && val > 0 {
				pageSize = int(val)
			}
		case "limit":
			if val, ok := v.(uint32); ok && val > 0 {
				limit = int(val)
			}
		case "offset":
			if withCount == 2 {
				if val, ok := v.(uint32); ok && val > 0 {
					mods = append(mods, qm.Offset(int(val)))
					previousCount = 1
				}
			}
		case "orderBy":
			if val, ok := v.(string); ok && len(val) > 0 {
				mods = append(mods, qm.OrderBy(val))
			}
		case "preMinId":
			if withCount == 3 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.OrderAdjustmentColumns.OrderAdjustmentID+" DESC"))
					mods = append(mods, model.OrderAdjustmentWhere.OrderAdjustmentID.LT(val))
					previousCount = 1
				}
			}
		case "preMaxId":
			if withCount == 4 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.OrderAdjustmentColumns.OrderAdjustmentID+" ASC"))
					mods = append(mods, model.OrderAdjustmentWhere.OrderAdjustmentID.GT(val))
					previousCount = 1
				}
			}
		case "select":
			if withCount != 5 {
				if val, ok := v.(string); ok && len(val) > 0 {
					selectCol = val
				}
			}
		}
	}

	for key, opMap := range filter {
		switch key {
		case model.OrderAdjustmentColumns.OrderAdjustmentID:
			mods = append(mods, modelx.GetIntMods(model.OrderAdjustmentColumns.OrderAdjustmentID, opMap)...)
		case model.OrderAdjustmentColumns.OrderID:
			mods = append(mods, modelx.GetIntMods(model.OrderAdjustmentColumns.OrderID, opMap)...)
		case model.OrderAdjustmentColumns.Amount:
			mods = append(mods, modelx.GetIntMods(model.OrderAdjustmentColumns.Amount, opMap)...)
		case model.OrderAdjustmentColumns.Memo:
			mods = append(mods, modelx.GetStringMods(model.OrderAdjustmentColumns.Memo, opMap)...)
		case model.OrderAdjustmentColumns.Status:
			mods = append(mods, modelx.GetIntMods(model.OrderAdjustmentColumns.Status, opMap)...)
		case model.OrderAdjustmentColumns.OperatedBy:
			mods = append(mods, modelx.GetIntMods(model.OrderAdjustmentColumns.OperatedBy, opMap)...)
		case model.OrderAdjustmentColumns.OperatedAt:
			mods = append(mods, modelx.GetTimeMods(model.OrderAdjustmentColumns.OperatedAt, opMap)...)
		}
	}

	if withCount >= 2 {
		if limit > 0 {
			mods = append(mods, qm.Limit(limit+1))
		}
	} else if withCount >= 0 {
		count, err = model.OrderAdjustments(mods...).Count(ctx, r.mysqlConn)
		if err != nil {
			return
		}

		if withCount == 0 {
			return
		}
	}

	if pageSize > 0 && (withCount == -1 || withCount == 1) {
		if page > 1 {
			mods = append(mods, qm.Offset(pageSize*(page-1)))
		}
		mods = append(mods, qm.Limit(pageSize))
	}

	var columns []string
	if len(selectCol) > 0 {
		if selectCol == "," {
			columns = append(columns, model.OrderAdjustmentColumns.OrderAdjustmentID)
		} else {
			columns = strings.Split(selectCol, ",")
		}
	}
	if len(columns) > 0 {
		mods = append(mods, qm.Select(columns...))
	}

	list, err = model.OrderAdjustments(mods...).All(ctx, r.mysqlConn)
	if err != nil {
		return
	}

	if withCount >= 2 {
		if limit > 0 && len(list) > limit {
			nextCount = 1
			list = list[:limit]
		}
		count = previousCount + nextCount*2
	}

	return
}

func (r *customOrderRepository) GetDiscountList(
	ctx context.Context,
	cols model.M,
	withCount int,
	filter map[string]map[string][]any,
) (list []*model.OrderDiscount, count int64, err error) {
	var page int
	var pageSize int
	var limit int
	var selectCol string
	var mods []qm.QueryMod
	var nextCount int64
	var previousCount int64
	for k, v := range cols {
		switch k {
		case "page":
			if val, ok := v.(uint64); ok && val > 1 {
				page = int(val)
			}
		case "pageSize":
			if val, ok := v.(uint64); ok && val > 0 {
				pageSize = int(val)
			}
		case "limit":
			if val, ok := v.(uint32); ok && val > 0 {
				limit = int(val)
			}
		case "offset":
			if withCount == 2 {
				if val, ok := v.(uint32); ok && val > 0 {
					mods = append(mods, qm.Offset(int(val)))
					previousCount = 1
				}
			}
		case "orderBy":
			if val, ok := v.(string); ok && len(val) > 0 {
				mods = append(mods, qm.OrderBy(val))
			}
		case "preMinId":
			if withCount == 3 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.OrderDiscountColumns.OrderDiscountID+" DESC"))
					mods = append(mods, model.OrderDiscountWhere.OrderDiscountID.LT(val))
					previousCount = 1
				}
			}
		case "preMaxId":
			if withCount == 4 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.OrderDiscountColumns.OrderDiscountID+" ASC"))
					mods = append(mods, model.OrderDiscountWhere.OrderDiscountID.GT(val))
					previousCount = 1
				}
			}
		case "select":
			if withCount != 5 {
				if val, ok := v.(string); ok && len(val) > 0 {
					selectCol = val
				}
			}
		}
	}

	for key, opMap := range filter {
		switch key {
		case model.OrderDiscountColumns.OrderDiscountID:
			mods = append(mods, modelx.GetIntMods(model.OrderDiscountColumns.OrderDiscountID, opMap)...)
		case model.OrderDiscountColumns.OrderID:
			mods = append(mods, modelx.GetIntMods(model.OrderDiscountColumns.OrderID, opMap)...)
		case model.OrderDiscountColumns.SkuID:
			mods = append(mods, modelx.GetIntMods(model.OrderDiscountColumns.SkuID, opMap)...)
		case model.OrderDiscountColumns.ProductID:
			mods = append(mods, modelx.GetIntMods(model.OrderDiscountColumns.ProductID, opMap)...)
		case model.OrderDiscountColumns.Title:
			mods = append(mods, modelx.GetStringMods(model.OrderDiscountColumns.Title, opMap)...)
		case model.OrderDiscountColumns.Slug:
			mods = append(mods, modelx.GetStringMods(model.OrderDiscountColumns.Slug, opMap)...)
		case model.OrderDiscountColumns.ActivityID:
			mods = append(mods, modelx.GetIntMods(model.OrderDiscountColumns.ActivityID, opMap)...)

		case model.OrderDiscountColumns.ActivityRuleID:
			mods = append(mods, modelx.GetIntMods(model.OrderDiscountColumns.ActivityRuleID, opMap)...)
		case model.OrderDiscountColumns.CouponTemplateID:
			mods = append(mods, modelx.GetIntMods(model.OrderDiscountColumns.CouponTemplateID, opMap)...)
		case model.OrderDiscountColumns.CouponID:
			mods = append(mods, modelx.GetIntMods(model.OrderDiscountColumns.CouponID, opMap)...)
		case model.OrderDiscountColumns.GrouponAmount:
			mods = append(mods, modelx.GetIntMods(model.OrderDiscountColumns.GrouponAmount, opMap)...)
		case model.OrderDiscountColumns.WholesaleAmount:
			mods = append(mods, modelx.GetIntMods(model.OrderDiscountColumns.WholesaleAmount, opMap)...)
		case model.OrderDiscountColumns.CouponAmount:
			mods = append(mods, modelx.GetIntMods(model.OrderDiscountColumns.CouponAmount, opMap)...)
		case model.OrderDiscountColumns.ActivityAmount:
			mods = append(mods, modelx.GetIntMods(model.OrderDiscountColumns.ActivityAmount, opMap)...)
		case model.OrderDiscountColumns.IntegralAmount:
			mods = append(mods, modelx.GetIntMods(model.OrderDiscountColumns.IntegralAmount, opMap)...)
		case model.OrderDiscountColumns.DiscountAmount:
			mods = append(mods, modelx.GetIntMods(model.OrderDiscountColumns.DiscountAmount, opMap)...)
		case model.OrderDiscountColumns.Integrals:
			mods = append(mods, modelx.GetIntMods(model.OrderDiscountColumns.Integrals, opMap)...)
		}
	}

	if withCount >= 2 {
		if limit > 0 {
			mods = append(mods, qm.Limit(limit+1))
		}
	} else if withCount >= 0 {
		count, err = model.OrderDiscounts(mods...).Count(ctx, r.mysqlConn)
		if err != nil {
			return
		}

		if withCount == 0 {
			return
		}
	}

	if pageSize > 0 && (withCount == -1 || withCount == 1) {
		if page > 1 {
			mods = append(mods, qm.Offset(pageSize*(page-1)))
		}
		mods = append(mods, qm.Limit(pageSize))
	}

	var columns []string
	if len(selectCol) > 0 {
		if selectCol == "," {
			columns = append(columns, model.OrderDiscountColumns.OrderDiscountID)
		} else {
			columns = strings.Split(selectCol, ",")
		}
	}
	if len(columns) > 0 {
		mods = append(mods, qm.Select(columns...))
	}

	list, err = model.OrderDiscounts(mods...).All(ctx, r.mysqlConn)
	if err != nil {
		return
	}

	if withCount >= 2 {
		if limit > 0 && len(list) > limit {
			nextCount = 1
			list = list[:limit]
		}
		count = previousCount + nextCount*2
	}

	return
}

func (r *customOrderRepository) GetItemList(
	ctx context.Context,
	cols model.M,
	withCount int,
	filter map[string]map[string][]any,
) (list []*model.OrderItem, count int64, err error) {
	var page int
	var pageSize int
	var limit int
	var selectCol string
	var mods []qm.QueryMod
	var nextCount int64
	var previousCount int64
	for k, v := range cols {
		switch k {
		case "page":
			if val, ok := v.(uint64); ok && val > 1 {
				page = int(val)
			}
		case "pageSize":
			if val, ok := v.(uint64); ok && val > 0 {
				pageSize = int(val)
			}
		case "limit":
			if val, ok := v.(uint32); ok && val > 0 {
				limit = int(val)
			}
		case "offset":
			if withCount == 2 {
				if val, ok := v.(uint32); ok && val > 0 {
					mods = append(mods, qm.Offset(int(val)))
					previousCount = 1
				}
			}
		case "orderBy":
			if val, ok := v.(string); ok && len(val) > 0 {
				mods = append(mods, qm.OrderBy(val))
			}
		case "preMinId":
			if withCount == 3 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.OrderItemColumns.OrderItemID+" DESC"))
					mods = append(mods, model.OrderItemWhere.OrderItemID.LT(val))
					previousCount = 1
				}
			}
		case "preMaxId":
			if withCount == 4 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.OrderItemColumns.OrderItemID+" ASC"))
					mods = append(mods, model.OrderItemWhere.OrderItemID.GT(val))
					previousCount = 1
				}
			}
		case "select":
			if withCount != 5 {
				if val, ok := v.(string); ok && len(val) > 0 {
					selectCol = val
				}
			}
		}
	}

	for key, opMap := range filter {
		switch key {
		case model.OrderItemColumns.OrderItemID:
			mods = append(mods, modelx.GetIntMods(model.OrderItemColumns.OrderItemID, opMap)...)
		case model.OrderItemColumns.OrderID:
			mods = append(mods, modelx.GetIntMods(model.OrderItemColumns.OrderID, opMap)...)
		case model.OrderItemColumns.SkuID:
			mods = append(mods, modelx.GetIntMods(model.OrderItemColumns.SkuID, opMap)...)
		case model.OrderItemColumns.Sku:
			mods = append(mods, modelx.GetStringMods(model.OrderItemColumns.Sku, opMap)...)
		case model.OrderItemColumns.SkuCode:
			mods = append(mods, modelx.GetStringMods(model.OrderItemColumns.SkuCode, opMap)...)
		case model.OrderItemColumns.SkuImageID:
			mods = append(mods, modelx.GetIntMods(model.OrderItemColumns.SkuImageID, opMap)...)
		case model.OrderItemColumns.ProductID:
			mods = append(mods, modelx.GetIntMods(model.OrderItemColumns.ProductID, opMap)...)
		case model.OrderItemColumns.ProductCode:
			mods = append(mods, modelx.GetStringMods(model.OrderItemColumns.ProductCode, opMap)...)
		case model.OrderItemColumns.EntryID:
			mods = append(mods, modelx.GetIntMods(model.OrderItemColumns.EntryID, opMap)...)
		case model.OrderItemColumns.Title:
			mods = append(mods, modelx.GetStringMods(model.OrderItemColumns.Title, opMap)...)
		case model.OrderItemColumns.Slug:
			mods = append(mods, modelx.GetStringMods(model.OrderItemColumns.Slug, opMap)...)

		case model.OrderItemColumns.ProductType:
			mods = append(mods, modelx.GetIntMods(model.OrderItemColumns.ProductType, opMap)...)
		case model.OrderItemColumns.BrandID:
			mods = append(mods, modelx.GetIntMods(model.OrderItemColumns.BrandID, opMap)...)
		case model.OrderItemColumns.BrandTitle:
			mods = append(mods, modelx.GetStringMods(model.OrderItemColumns.BrandTitle, opMap)...)
		case model.OrderItemColumns.BrandSlug:
			mods = append(mods, modelx.GetStringMods(model.OrderItemColumns.BrandSlug, opMap)...)
		case model.OrderItemColumns.GemPrice:
			mods = append(mods, modelx.GetIntMods(model.OrderItemColumns.GemPrice, opMap)...)
		case model.OrderItemColumns.RetailPrice:
			mods = append(mods, modelx.GetIntMods(model.OrderItemColumns.RetailPrice, opMap)...)
		case model.OrderItemColumns.Quantity:
			mods = append(mods, modelx.GetIntMods(model.OrderItemColumns.Quantity, opMap)...)
		case model.OrderItemColumns.Weight:
			mods = append(mods, modelx.GetIntMods(model.OrderItemColumns.Weight, opMap)...)
		case model.OrderItemColumns.TradeState:
			mods = append(mods, modelx.GetIntMods(model.OrderItemColumns.TradeState, opMap)...)
		case model.OrderItemColumns.Status:
			mods = append(mods, modelx.GetIntMods(model.OrderItemColumns.Status, opMap)...)
		case model.OrderItemColumns.GemAmount:
			mods = append(mods, modelx.GetIntMods(model.OrderItemColumns.GemAmount, opMap)...)
		case model.OrderItemColumns.RetailAmount:
			mods = append(mods, modelx.GetIntMods(model.OrderItemColumns.RetailAmount, opMap)...)
		case model.OrderItemColumns.Freight:
			mods = append(mods, modelx.GetIntMods(model.OrderItemColumns.Freight, opMap)...)
		case model.OrderItemColumns.DiscountAmount:
			mods = append(mods, modelx.GetIntMods(model.OrderItemColumns.DiscountAmount, opMap)...)
		case model.OrderItemColumns.AdjustAmount:
			mods = append(mods, modelx.GetIntMods(model.OrderItemColumns.AdjustAmount, opMap)...)
		case model.OrderItemColumns.ActualAmount:
			mods = append(mods, modelx.GetIntMods(model.OrderItemColumns.ActualAmount, opMap)...)
		case model.OrderItemColumns.RefundAmount:
			mods = append(mods, modelx.GetIntMods(model.OrderItemColumns.RefundAmount, opMap)...)
		case model.OrderItemColumns.RefundQuantity:
			mods = append(mods, modelx.GetIntMods(model.OrderItemColumns.RefundQuantity, opMap)...)
		case model.OrderItemColumns.PostID:
			mods = append(mods, modelx.GetIntMods(model.OrderItemColumns.PostID, opMap)...)
		case model.OrderItemColumns.InviterID:
			mods = append(mods, modelx.GetIntMods(model.OrderItemColumns.InviterID, opMap)...)
		}
	}

	if withCount >= 2 {
		if limit > 0 {
			mods = append(mods, qm.Limit(limit+1))
		}
	} else if withCount >= 0 {
		count, err = model.OrderItems(mods...).Count(ctx, r.mysqlConn)
		if err != nil {
			return
		}

		if withCount == 0 {
			return
		}
	}

	if pageSize > 0 && (withCount == -1 || withCount == 1) {
		if page > 1 {
			mods = append(mods, qm.Offset(pageSize*(page-1)))
		}
		mods = append(mods, qm.Limit(pageSize))
	}

	var columns []string
	if len(selectCol) > 0 {
		if selectCol == "," {
			columns = append(columns, model.OrderItemColumns.OrderItemID)
		} else {
			columns = strings.Split(selectCol, ",")
		}
	}
	if len(columns) > 0 {
		mods = append(mods, qm.Select(columns...))
	}

	list, err = model.OrderItems(mods...).All(ctx, r.mysqlConn)
	if err != nil {
		return
	}

	if withCount >= 2 {
		if limit > 0 && len(list) > limit {
			nextCount = 1
			list = list[:limit]
		}
		count = previousCount + nextCount*2
	}

	return
}

func (r *customOrderRepository) GetLogList(
	ctx context.Context,
	cols model.M,
	withCount int,
	filter map[string]map[string][]any,
) (list []*model.OrderOperateLog, count int64, err error) {
	var page int
	var pageSize int
	var limit int
	var selectCol string
	var mods []qm.QueryMod
	var nextCount int64
	var previousCount int64
	for k, v := range cols {
		switch k {
		case "page":
			if val, ok := v.(uint64); ok && val > 1 {
				page = int(val)
			}
		case "pageSize":
			if val, ok := v.(uint64); ok && val > 0 {
				pageSize = int(val)
			}
		case "limit":
			if val, ok := v.(uint32); ok && val > 0 {
				limit = int(val)
			}
		case "offset":
			if withCount == 2 {
				if val, ok := v.(uint32); ok && val > 0 {
					mods = append(mods, qm.Offset(int(val)))
					previousCount = 1
				}
			}
		case "orderBy":
			if val, ok := v.(string); ok && len(val) > 0 {
				mods = append(mods, qm.OrderBy(val))
			}
		case "preMinId":
			if withCount == 3 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.OrderOperateLogColumns.LogID+" DESC"))
					mods = append(mods, model.OrderOperateLogWhere.LogID.LT(val))
					previousCount = 1
				}
			}
		case "preMaxId":
			if withCount == 4 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.OrderOperateLogColumns.LogID+" ASC"))
					mods = append(mods, model.OrderOperateLogWhere.LogID.GT(val))
					previousCount = 1
				}
			}
		case "select":
			if withCount != 5 {
				if val, ok := v.(string); ok && len(val) > 0 {
					selectCol = val
				}
			}
		}
	}

	for key, opMap := range filter {
		switch key {
		case model.OrderOperateLogColumns.LogID:
			mods = append(mods, modelx.GetIntMods(model.OrderOperateLogColumns.LogID, opMap)...)
		case model.OrderOperateLogColumns.OrderID:
			mods = append(mods, modelx.GetIntMods(model.OrderOperateLogColumns.OrderID, opMap)...)
		case model.OrderOperateLogColumns.TradeState:
			mods = append(mods, modelx.GetIntMods(model.OrderOperateLogColumns.TradeState, opMap)...)
		case model.OrderOperateLogColumns.NewState:
			mods = append(mods, modelx.GetIntMods(model.OrderOperateLogColumns.NewState, opMap)...)
		case model.OrderOperateLogColumns.Type:
			mods = append(mods, modelx.GetIntMods(model.OrderOperateLogColumns.Type, opMap)...)
		case model.OrderOperateLogColumns.Name:
			mods = append(mods, modelx.GetStringMods(model.OrderOperateLogColumns.Name, opMap)...)
		case model.OrderOperateLogColumns.Code:
			mods = append(mods, modelx.GetStringMods(model.OrderOperateLogColumns.Code, opMap)...)
		case model.OrderOperateLogColumns.Status:
			mods = append(mods, modelx.GetIntMods(model.OrderOperateLogColumns.Status, opMap)...)
		case model.OrderOperateLogColumns.Memo:
			mods = append(mods, modelx.GetStringMods(model.OrderOperateLogColumns.Memo, opMap)...)
		case model.OrderOperateLogColumns.OperatedBy:
			mods = append(mods, modelx.GetIntMods(model.OrderOperateLogColumns.OperatedBy, opMap)...)
		case model.OrderOperateLogColumns.OperatedAt:
			mods = append(mods, modelx.GetTimeMods(model.OrderOperateLogColumns.OperatedAt, opMap)...)
		}
	}

	if withCount >= 2 {
		if limit > 0 {
			mods = append(mods, qm.Limit(limit+1))
		}
	} else if withCount >= 0 {
		count, err = model.OrderOperateLogs(mods...).Count(ctx, r.mysqlConn)
		if err != nil {
			return
		}

		if withCount == 0 {
			return
		}
	}

	if pageSize > 0 && (withCount == -1 || withCount == 1) {
		if page > 1 {
			mods = append(mods, qm.Offset(pageSize*(page-1)))
		}
		mods = append(mods, qm.Limit(pageSize))
	}

	var columns []string
	if len(selectCol) > 0 {
		if selectCol == "," {
			columns = append(columns, model.OrderOperateLogColumns.LogID)
		} else {
			columns = strings.Split(selectCol, ",")
		}
	}
	if len(columns) > 0 {
		mods = append(mods, qm.Select(columns...))
	}

	list, err = model.OrderOperateLogs(mods...).All(ctx, r.mysqlConn)
	if err != nil {
		return
	}

	if withCount >= 2 {
		if limit > 0 && len(list) > limit {
			nextCount = 1
			list = list[:limit]
		}
		count = previousCount + nextCount*2
	}

	return
}

func (r *customOrderRepository) GetPaymentList(
	ctx context.Context,
	cols model.M,
	withCount int,
	filter map[string]map[string][]any,
) (list []*model.OrderPayment, count int64, err error) {
	var page int
	var pageSize int
	var limit int
	var selectCol string
	var mods []qm.QueryMod
	var nextCount int64
	var previousCount int64
	for k, v := range cols {
		switch k {
		case "page":
			if val, ok := v.(uint64); ok && val > 1 {
				page = int(val)
			}
		case "pageSize":
			if val, ok := v.(uint64); ok && val > 0 {
				pageSize = int(val)
			}
		case "limit":
			if val, ok := v.(uint32); ok && val > 0 {
				limit = int(val)
			}
		case "offset":
			if withCount == 2 {
				if val, ok := v.(uint32); ok && val > 0 {
					mods = append(mods, qm.Offset(int(val)))
					previousCount = 1
				}
			}
		case "orderBy":
			if val, ok := v.(string); ok && len(val) > 0 {
				mods = append(mods, qm.OrderBy(val))
			}
		case "preMinId":
			if withCount == 3 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.OrderPaymentColumns.OrderPaymentID+" DESC"))
					mods = append(mods, model.OrderPaymentWhere.OrderPaymentID.LT(val))
					previousCount = 1
				}
			}
		case "preMaxId":
			if withCount == 4 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.OrderPaymentColumns.OrderPaymentID+" ASC"))
					mods = append(mods, model.OrderPaymentWhere.OrderPaymentID.GT(val))
					previousCount = 1
				}
			}
		case "select":
			if withCount != 5 {
				if val, ok := v.(string); ok && len(val) > 0 {
					selectCol = val
				}
			}
		}
	}

	for key, opMap := range filter {
		switch key {
		case model.OrderPaymentColumns.OrderPaymentID:
			mods = append(mods, modelx.GetIntMods(model.OrderPaymentColumns.OrderPaymentID, opMap)...)
		case model.OrderPaymentColumns.OrderID:
			mods = append(mods, modelx.GetIntMods(model.OrderPaymentColumns.OrderID, opMap)...)
		case model.OrderPaymentColumns.No:
			mods = append(mods, modelx.GetStringMods(model.OrderPaymentColumns.No, opMap)...)
		case model.OrderPaymentColumns.TransactionID:
			mods = append(mods, modelx.GetStringMods(model.OrderPaymentColumns.TransactionID, opMap)...)
		case model.OrderPaymentColumns.Amount:
			mods = append(mods, modelx.GetIntMods(model.OrderPaymentColumns.Amount, opMap)...)
		case model.OrderPaymentColumns.Type:
			mods = append(mods, modelx.GetIntMods(model.OrderPaymentColumns.Type, opMap)...)
		case model.OrderPaymentColumns.Name:
			mods = append(mods, modelx.GetStringMods(model.OrderPaymentColumns.Name, opMap)...)
		case model.OrderPaymentColumns.Code:
			mods = append(mods, modelx.GetStringMods(model.OrderPaymentColumns.Code, opMap)...)
		case model.OrderPaymentColumns.Status:
			mods = append(mods, modelx.GetIntMods(model.OrderPaymentColumns.Status, opMap)...)
		case model.OrderPaymentColumns.PaidAt:
			mods = append(mods, modelx.GetTimeMods(model.OrderPaymentColumns.PaidAt, opMap)...)
		}
	}

	if withCount >= 2 {
		if limit > 0 {
			mods = append(mods, qm.Limit(limit+1))
		}
	} else if withCount >= 0 {
		count, err = model.OrderPayments(mods...).Count(ctx, r.mysqlConn)
		if err != nil {
			return
		}

		if withCount == 0 {
			return
		}
	}

	if pageSize > 0 && (withCount == -1 || withCount == 1) {
		if page > 1 {
			mods = append(mods, qm.Offset(pageSize*(page-1)))
		}
		mods = append(mods, qm.Limit(pageSize))
	}

	var columns []string
	if len(selectCol) > 0 {
		if selectCol == "," {
			columns = append(columns, model.OrderPaymentColumns.OrderPaymentID)
		} else {
			columns = strings.Split(selectCol, ",")
		}
	}
	if len(columns) > 0 {
		mods = append(mods, qm.Select(columns...))
	}

	list, err = model.OrderPayments(mods...).All(ctx, r.mysqlConn)
	if err != nil {
		return
	}

	if withCount >= 2 {
		if limit > 0 && len(list) > limit {
			nextCount = 1
			list = list[:limit]
		}
		count = previousCount + nextCount*2
	}

	return
}

func (r *customOrderRepository) GetShipmentList(
	ctx context.Context,
	cols model.M,
	withCount int,
	filter map[string]map[string][]any,
) (list []*model.OrderShipment, count int64, err error) {
	var page int
	var pageSize int
	var limit int
	var selectCol string
	var mods []qm.QueryMod
	var nextCount int64
	var previousCount int64
	for k, v := range cols {
		switch k {
		case "page":
			if val, ok := v.(uint64); ok && val > 1 {
				page = int(val)
			}
		case "pageSize":
			if val, ok := v.(uint64); ok && val > 0 {
				pageSize = int(val)
			}
		case "limit":
			if val, ok := v.(uint32); ok && val > 0 {
				limit = int(val)
			}
		case "offset":
			if withCount == 2 {
				if val, ok := v.(uint32); ok && val > 0 {
					mods = append(mods, qm.Offset(int(val)))
					previousCount = 1
				}
			}
		case "orderBy":
			if val, ok := v.(string); ok && len(val) > 0 {
				mods = append(mods, qm.OrderBy(val))
			}
		case "preMinId":
			if withCount == 3 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.OrderShipmentColumns.OrderShipmentID+" DESC"))
					mods = append(mods, model.OrderShipmentWhere.OrderShipmentID.LT(val))
					previousCount = 1
				}
			}
		case "preMaxId":
			if withCount == 4 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.OrderShipmentColumns.OrderShipmentID+" ASC"))
					mods = append(mods, model.OrderShipmentWhere.OrderShipmentID.GT(val))
					previousCount = 1
				}
			}
		case "select":
			if withCount != 5 {
				if val, ok := v.(string); ok && len(val) > 0 {
					selectCol = val
				}
			}
		}
	}

	for key, opMap := range filter {
		switch key {
		case model.OrderShipmentColumns.OrderShipmentID:
			mods = append(mods, modelx.GetIntMods(model.OrderShipmentColumns.OrderShipmentID, opMap)...)
		case model.OrderShipmentColumns.OrderID:
			mods = append(mods, modelx.GetIntMods(model.OrderShipmentColumns.OrderID, opMap)...)
		case model.OrderShipmentColumns.No:
			mods = append(mods, modelx.GetStringMods(model.OrderShipmentColumns.No, opMap)...)
		case model.OrderShipmentColumns.OrderType:
			mods = append(mods, modelx.GetIntMods(model.OrderShipmentColumns.OrderType, opMap)...)
		case model.OrderShipmentColumns.Type:
			mods = append(mods, modelx.GetIntMods(model.OrderShipmentColumns.Type, opMap)...)
		case model.OrderShipmentColumns.Name:
			mods = append(mods, modelx.GetStringMods(model.OrderShipmentColumns.Name, opMap)...)
		case model.OrderShipmentColumns.Code:
			mods = append(mods, modelx.GetStringMods(model.OrderShipmentColumns.Code, opMap)...)
		case model.OrderShipmentColumns.Status:
			mods = append(mods, modelx.GetIntMods(model.OrderShipmentColumns.Status, opMap)...)
		case model.OrderShipmentColumns.UpdatedAt:
			mods = append(mods, modelx.GetTimeMods(model.OrderShipmentColumns.UpdatedAt, opMap)...)
		}
	}

	if withCount >= 2 {
		if limit > 0 {
			mods = append(mods, qm.Limit(limit+1))
		}
	} else if withCount >= 0 {
		count, err = model.OrderShipments(mods...).Count(ctx, r.mysqlConn)
		if err != nil {
			return
		}

		if withCount == 0 {
			return
		}
	}

	if pageSize > 0 && (withCount == -1 || withCount == 1) {
		if page > 1 {
			mods = append(mods, qm.Offset(pageSize*(page-1)))
		}
		mods = append(mods, qm.Limit(pageSize))
	}

	var columns []string
	if len(selectCol) > 0 {
		if selectCol == "," {
			columns = append(columns, model.OrderShipmentColumns.OrderShipmentID)
		} else {
			columns = strings.Split(selectCol, ",")
		}
	}
	if len(columns) > 0 {
		mods = append(mods, qm.Select(columns...))
	}

	list, err = model.OrderShipments(mods...).All(ctx, r.mysqlConn)
	if err != nil {
		return
	}

	if withCount >= 2 {
		if limit > 0 && len(list) > limit {
			nextCount = 1
			list = list[:limit]
		}
		count = previousCount + nextCount*2
	}

	return
}

func (r *customOrderRepository) GetRefundList(
	ctx context.Context,
	cols model.M,
	withCount int,
	filter map[string]map[string][]any,
) (list []*model.OrderRefund, count int64, err error) {
	var page int
	var pageSize int
	var limit int
	var selectCol string
	var mods []qm.QueryMod
	var nextCount int64
	var previousCount int64
	for k, v := range cols {
		switch k {
		case "page":
			if val, ok := v.(uint64); ok && val > 1 {
				page = int(val)
			}
		case "pageSize":
			if val, ok := v.(uint64); ok && val > 0 {
				pageSize = int(val)
			}
		case "limit":
			if val, ok := v.(uint32); ok && val > 0 {
				limit = int(val)
			}
		case "offset":
			if withCount == 2 {
				if val, ok := v.(uint32); ok && val > 0 {
					mods = append(mods, qm.Offset(int(val)))
					previousCount = 1
				}
			}
		case "orderBy":
			if val, ok := v.(string); ok && len(val) > 0 {
				mods = append(mods, qm.OrderBy(val))
			}
		case "preMinId":
			if withCount == 3 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.OrderRefundColumns.OrderRefundID+" DESC"))
					mods = append(mods, model.OrderRefundWhere.OrderRefundID.LT(val))
					previousCount = 1
				}
			}
		case "preMaxId":
			if withCount == 4 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.OrderRefundColumns.OrderRefundID+" ASC"))
					mods = append(mods, model.OrderRefundWhere.OrderRefundID.GT(val))
					previousCount = 1
				}
			}
		case "select":
			if withCount != 5 {
				if val, ok := v.(string); ok && len(val) > 0 {
					selectCol = val
				}
			}
		}
	}

	for key, opMap := range filter {
		switch key {
		case model.OrderRefundColumns.OrderRefundID:
			mods = append(mods, modelx.GetIntMods(model.OrderRefundColumns.OrderRefundID, opMap)...)
		case model.OrderRefundColumns.OrderID:
			mods = append(mods, modelx.GetIntMods(model.OrderRefundColumns.OrderID, opMap)...)
		case model.OrderRefundColumns.OrderPaymentID:
			mods = append(mods, modelx.GetIntMods(model.OrderRefundColumns.OrderPaymentID, opMap)...)
		case model.OrderRefundColumns.RefundNo:
			mods = append(mods, modelx.GetStringMods(model.OrderRefundColumns.RefundNo, opMap)...)
		case model.OrderRefundColumns.RefundID:
			mods = append(mods, modelx.GetStringMods(model.OrderRefundColumns.RefundID, opMap)...)
		case model.OrderRefundColumns.Amount:
			mods = append(mods, modelx.GetIntMods(model.OrderRefundColumns.Amount, opMap)...)
		case model.OrderRefundColumns.Status:
			mods = append(mods, modelx.GetIntMods(model.OrderRefundColumns.Status, opMap)...)
		case model.OrderRefundColumns.RefundAt:
			mods = append(mods, modelx.GetTimeMods(model.OrderRefundColumns.RefundAt, opMap)...)
		}
	}

	if withCount >= 2 {
		if limit > 0 {
			mods = append(mods, qm.Limit(limit+1))
		}
	} else if withCount >= 0 {
		count, err = model.OrderRefunds(mods...).Count(ctx, r.mysqlConn)
		if err != nil {
			return
		}

		if withCount == 0 {
			return
		}
	}

	if pageSize > 0 && (withCount == -1 || withCount == 1) {
		if page > 1 {
			mods = append(mods, qm.Offset(pageSize*(page-1)))
		}
		mods = append(mods, qm.Limit(pageSize))
	}

	var columns []string
	if len(selectCol) > 0 {
		if selectCol == "," {
			columns = append(columns, model.OrderRefundColumns.OrderRefundID)
		} else {
			columns = strings.Split(selectCol, ",")
		}
	}
	if len(columns) > 0 {
		mods = append(mods, qm.Select(columns...))
	}

	list, err = model.OrderRefunds(mods...).All(ctx, r.mysqlConn)
	if err != nil {
		return
	}

	if withCount >= 2 {
		if limit > 0 && len(list) > limit {
			nextCount = 1
			list = list[:limit]
		}
		count = previousCount + nextCount*2
	}

	return
}
func (r *customOrderRepository) UpdateShipment(
	ctx context.Context,
	tx boil.ContextExecutor,
	data *model.OrderShipment,
) error {
	var db boil.ContextExecutor
	if tx != nil {
		db = tx
	} else {
		db = r.mysqlConn
	}

	rowsAff, err := data.Update(ctx, db, boil.Blacklist(
		model.OrderShipmentColumns.OrderShipmentID,
		model.OrderShipmentColumns.OrderID,
		model.OrderShipmentColumns.Type,
	))
	if err != nil {
		return err
	}

	if rowsAff == 0 {
		return model.ErrNotUpdated
	}

	return nil
}

func (r *customOrderRepository) InsertShipment(
	ctx context.Context,
	tx boil.ContextExecutor,
	data *model.OrderShipment,
) error {
	var db boil.ContextExecutor
	if tx != nil {
		db = tx
	} else {
		db = r.mysqlConn
	}

	err := data.Insert(ctx, db, boil.Infer())
	if err != nil {
		return err
	}

	return nil
}
